#include "ControlModuleParametersWidget.h"
#include "ui_ControlModuleParametersWidget.h"
#include "ScanCameraDevice.h"
#include <QDebug>

/**
 * @brief ControlModuleParametersWidget构造函数
 * 
 * 初始化UI界面，并根据提供的设备指针建立连接和初始化参数
 * 如果设备指针有效，从设备获取当前参数并设置UI；否则设置默认值
 * 
 * @param device 扫描相机设备指针
 * @param parent 父窗口指针
 */
ControlModuleParametersWidget::ControlModuleParametersWidget(ScanCameraDevice* device, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ControlModuleParametersWidget),
    m_device(device)
{
    ui->setupUi(this);
    // 如果提供了设备指针，建立与设备的直接连接
    if (m_device)
    {
        fetchParametersFromDevice();
        connectToDevice();
    } else {
        // 仅当没有设备连接时设置默认值
        setScanGear(1);
        setGain1(0);
        setGain2(0);
        setCathodeGating(false);
        setDelayTime(0);
        setPulseWidth(0);
    }
}

/**
 * @brief ControlModuleParametersWidget析构函数
 * 
 * 释放UI资源
 */
ControlModuleParametersWidget::~ControlModuleParametersWidget()
{
    delete ui;
}

/**
 * @brief 快门开关
 * @param open true-打开，false-关闭
 */
void ControlModuleParametersWidget::setShutterControl(bool open)
{
    // 取消连接快门控制开关信号到设备方法
    disconnect(ui->widget_ShutterControl, &SwitchSliderWidget::toggled, this, &ControlModuleParametersWidget::onShutterControlToggled);
    ui->widget_ShutterControl->setChecked(open);
    // 连接快门控制开关信号到设备方法
    connect(ui->widget_ShutterControl, &SwitchSliderWidget::toggled, this, &ControlModuleParametersWidget::onShutterControlToggled);
}

/**
 * @brief 设置扫描档位
 * 将档位值转换为下拉框索引并设置当前选中项
 * @param gear 档位值，1:快组件, 2:中组件, 3:慢组件
 */
void ControlModuleParametersWidget::setScanGear(int gear)
{
    // 取消直接连接扫描档位下拉框到设备方法
    disconnect(ui->scanGearComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ControlModuleParametersWidget::onScanGearComboBoxChanged);

    // 档位从0开始索引，需要减1转换为下拉框索引
    int index = gear - 1;
    if (index >= 0 && index < ui->scanGearComboBox->count()) {
        ui->scanGearComboBox->setCurrentIndex(index);
    }
    // 直接连接扫描档位下拉框到设备方法
    connect(ui->scanGearComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ControlModuleParametersWidget::onScanGearComboBoxChanged);

}

/**
 * @brief 设置增益1值
 * 更新增益1的SpinBox控件显示
 * @param value 增益1的值
 */
void ControlModuleParametersWidget::setGain1(int value)
{
    // 取消直接连接增益1 SpinBox到设备方法
    disconnect(ui->gain1SpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onGain1ValueChanged);
    ui->gain1SpinBox->setValue(value);
    // 直接连接增益1 SpinBox到设备方法
    connect(ui->gain1SpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onGain1ValueChanged);
}

/**
 * @brief 设置增益2值
 * 更新增益2的SpinBox控件显示
 * @param value 增益2的值
 */
void ControlModuleParametersWidget::setGain2(int value)
{
    // 取消直接连接增益2 SpinBox到设备方法
    disconnect(ui->gain2SpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onGain2ValueChanged);
    ui->gain2SpinBox->setValue(value);
    // 直接连接增益2 SpinBox到设备方法
    connect(ui->gain2SpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onGain2ValueChanged);
}

/**
 * @brief 设置阴极门控状态
 * 更新阴极门控开关控件的状态
 * @param cathodeGatingMode 阴极门控模式
 */
void ControlModuleParametersWidget::setCathodeGating(uint8_t cathodeGatingMode)
{
    // 取消连接阴极门控开关控件到设备方法
    disconnect(ui->widget_CathodeGating, &SwitchSliderWidget::toggled, this, &ControlModuleParametersWidget::onCathodeGatingToggled);

    // 取消连接外部触发开关控件到设备方法
    disconnect(ui->widget_External, &SwitchSliderWidget::toggled, this, &ControlModuleParametersWidget::onExternalToggled);

    ui->widget_CathodeGating->setChecked(cathodeGatingMode==1||cathodeGatingMode==2);
    ui->widget_External->setChecked(cathodeGatingMode==1);

    // 连接阴极门控开关控件到设备方法
    connect(ui->widget_CathodeGating, &SwitchSliderWidget::toggled, this, &ControlModuleParametersWidget::onCathodeGatingToggled);

    // 连接外部触发开关控件到设备方法
    connect(ui->widget_External, &SwitchSliderWidget::toggled, this, &ControlModuleParametersWidget::onExternalToggled);
}

/**
 * @brief 设置延迟时间
 * 更新延迟时间SpinBox控件显示
 * @param time 延迟时间，单位：ns
 */
void ControlModuleParametersWidget::setDelayTime(uint32_t time)
{
    // 取消当延迟时间改变时，重新设置阴极门控
    disconnect(ui->delayTimeSpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onDelayTimeValueChanged);
    ui->delayTimeSpinBox->setValue(time/1000);
    // 当延迟时间改变时，重新设置阴极门控
    connect(ui->delayTimeSpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onDelayTimeValueChanged);
}

/**
 * @brief 设置脉冲宽度
 * 更新脉冲宽度SpinBox控件显示
 * @param width 脉冲宽度，单位：ns
 */
void ControlModuleParametersWidget::setPulseWidth(uint32_t time)
{
    // 取消当脉冲宽度改变时，重新设置阴极门控
    disconnect(ui->pulseWidthSpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onPulseWidthValueChanged);
    ui->pulseWidthSpinBox->setValue(time/1000);
    // 当脉冲宽度改变时，重新设置阴极门控
    connect(ui->pulseWidthSpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onPulseWidthValueChanged);
}

/**
 * @brief 快门开关
 * @return open true-打开，false-关闭
 */
bool ControlModuleParametersWidget::getShutterControl()
{
    return ui->widget_ShutterControl->isChecked();
}

/**
 * @brief 获取当前扫描档位
 * 从下拉框索引转换为实际档位值
 * @return int 档位值，1:快组件, 2:中组件, 3:慢组件
 */
int ControlModuleParametersWidget::getScanGear() const
{
    // 下拉框索引从0开始，需要加1转换为实际档位值
    return ui->scanGearComboBox->currentIndex() + 1;
}

/**
 * @brief 获取当前增益1值
 * @return int 增益1的值
 */
uint16_t ControlModuleParametersWidget::getGain1() const
{
    return ui->gain1SpinBox->value();
}

/**
 * @brief 获取当前增益2值
 * @return int 增益2的值
 */
uint16_t ControlModuleParametersWidget::getGain2() const
{
    return ui->gain2SpinBox->value();
}

/**
 * @brief 获取阴极门控启用状态
 * @return 用阴极门控模式 （1:门控开+外触发, 2:门控开, 3:门控关）
 */
uint8_t ControlModuleParametersWidget::getCathodeGatingMode() const
{
    uint8_t mode=ui->widget_CathodeGating->isChecked()?2:3;
    mode=ui->widget_External->isChecked()&&2==mode?1:mode;
    return mode;
}

/**
 * @brief 获取当前延迟时间
 * @return int 延迟时间，单位：nm
 */
uint32_t ControlModuleParametersWidget::getDelayTime() const
{
    return ui->delayTimeSpinBox->value()*1000;
}

/**
 * @brief 获取当前脉冲宽度
 * @return int 脉冲宽度，单位：nm
 */
uint32_t ControlModuleParametersWidget::getPulseWidth() const
{
    return ui->pulseWidthSpinBox->value()*1000;
}

/**
 * @brief ControlModuleParametersWidget::updateConfig 当配置参数变化时更新UI
 * @param vmap
 */
void ControlModuleParametersWidget::updateConfig(QVariantMap vmap)
{
    ui->widget_ShutterControl->setEnabled(vmap["ShutterEnable"].toBool());
    ui->gain1SpinBox->setEnabled(vmap["Gain1Enable"].toBool());
    ui->gain2SpinBox->setEnabled(vmap["Gain2Enable"].toBool());
    ui->cathode_external_widget->setEnabled(vmap["CathodeControlEnable"].toBool());
    ui->delay_time_pulse_width_widget->setEnabled(vmap["CathodeControlEnable"].toBool());
}

/**
 * @brief 获取当前设备指针
 * 
 * @return ScanCameraDevice* 设备指针
 */
ScanCameraDevice* ControlModuleParametersWidget::getDevice() const
{
    return m_device;
}

/**
 * @brief 从设备获取参数并更新UI
 * 
 * 正确使用getParameter方法获取各项参数，包括扫描档位、MCP增益和阴极门控参数
 *
 */
void ControlModuleParametersWidget::fetchParametersFromDevice()
{
    if (!m_device) {
        return;
    }
    //设置快门
    setShutterControl(m_device->getParameter("ShutterOpen").toBool());

    //设置扫描档位
    setScanGear(m_device->getParameter("ComponentSelection").toInt());

    // 设置MCP增益参数
    setGain1(m_device->getParameter("MCPGain1").toInt());
    setGain2(m_device->getParameter("MCPGain2").toInt());

    // 设置阴极门控参数
    QVariant cathodeGatingMode = m_device->getParameter("CathodeGatingMode");
    setCathodeGating(m_device->getParameter("CathodeGatingMode").toUInt());
    setDelayTime(m_device->getParameter("CathodeGatingDelayNs").toUInt());
    setPulseWidth(m_device->getParameter("CathodeGatingPulseWidthNs").toUInt());
}

void ControlModuleParametersWidget::disconnectFromDevice()
{
    // 断开所有UI控件的信号连接
    disconnect(ui->scanGearComboBox, nullptr, this, nullptr);
    disconnect(ui->gain1SpinBox, nullptr, this, nullptr);
    disconnect(ui->gain2SpinBox, nullptr, this, nullptr);
    
    // 断开阴极门控开关控件的信号连接
    disconnect(ui->widget_CathodeGating, nullptr, this, nullptr);
    
    disconnect(ui->delayTimeSpinBox, nullptr, this, nullptr);
    disconnect(ui->pulseWidthSpinBox, nullptr, this, nullptr);
    
    // 断开快门控制控件的连接
    disconnect(ui->widget_ShutterControl, nullptr, this, nullptr);
    
    // 断开与设备的直接连接
    if (m_device) {
        disconnect(this, nullptr, m_device, nullptr);
        disconnect(m_device, nullptr, this, nullptr);
    }
    
    qDebug() << "Disconnected from device in ControlModuleParametersWidget";
}

void ControlModuleParametersWidget::onSyncParameters()
{
    fetchParametersFromDevice();
}

/**
 * @brief 建立与设备的直接对接
 * 
 * 将UI控件信号直接连接到设备方法，实现参数的实时更新
 * 在建立新连接前，先断开所有现有连接
 */
void ControlModuleParametersWidget::connectToDevice()
{
    if (!m_device) return;
    
    // 移除原有的信号槽连接，避免重复连接
    disconnectFromDevice();
    
    // 连接快门控制开关信号到设备方法
    connect(ui->widget_ShutterControl, &SwitchSliderWidget::toggled, this, &ControlModuleParametersWidget::onShutterControlToggled);

    // 直接连接扫描档位下拉框到设备方法
    connect(ui->scanGearComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ControlModuleParametersWidget::onScanGearComboBoxChanged);
    
    // 直接连接增益1 SpinBox到设备方法
    connect(ui->gain1SpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onGain1ValueChanged);
    
    // 直接连接增益2 SpinBox到设备方法
    connect(ui->gain2SpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onGain2ValueChanged);
    
    // 连接阴极门控开关控件到设备方法
    connect(ui->widget_CathodeGating, &SwitchSliderWidget::toggled, this, &ControlModuleParametersWidget::onCathodeGatingToggled);
    
    // 连接外部触发开关控件到设备方法
    connect(ui->widget_External, &SwitchSliderWidget::toggled, this, &ControlModuleParametersWidget::onExternalToggled);

    // 当延迟时间改变时，重新设置阴极门控
    connect(ui->delayTimeSpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onDelayTimeValueChanged);
    
    // 当脉冲宽度改变时，重新设置阴极门控
    connect(ui->pulseWidthSpinBox, &QSpinBox::editingFinished, this, &ControlModuleParametersWidget::onPulseWidthValueChanged);

}

/**
 * @brief 快门控制开关槽函数实现
 */
void ControlModuleParametersWidget::onShutterControlToggled(bool checked)
{
    if (!m_device) return;
    
    CommandResult result = m_device->setShutterControl(checked);
    if(CommandResult::Success==result)
    {
        emit writeLog(QString("快门%1成功!").arg(checked?"打开":"关闭"),0,true);
    }
    else
    {
        emit writeLog(QString("快门%1失败!").arg(checked?"打开":"关闭"),2,false);
    }
    emit syncParameters();
}

/**
 * @brief 扫描档位下拉框槽函数实现
 */
void ControlModuleParametersWidget::onScanGearComboBoxChanged(int index)
{
    if (!m_device) return;
    
    static QString logMsg[]={"快","中","慢"};
    // 映射档位索引到实际档位值
    uint8_t componentSelection = index+1; // 1:快组件, 2:中组件, 3:慢组件
    uint8_t gearPosition;
    switch(componentSelection)
    {
        case 1:
        {
            gearPosition= m_device->getParameter("FastGearPosition").toUInt();
        }break;
        case 2:
        {
            gearPosition= m_device->getParameter("MiddleGearPosition").toUInt();
        }break;
        case 3:
        {
            gearPosition= m_device->getParameter("SlowGearPosition").toUInt();
        }break;
        default:
            return;
    }
    // 直接调用设备的setScanGear方法
    CommandResult result = m_device->setGearPosition(gearPosition,componentSelection);
    if(CommandResult::Success==result)
    {
        emit writeLog(QString("%1档位设置成功!").arg(logMsg[componentSelection-1]),0,true);
    }
    else
    {
        emit writeLog(QString("%1档位设置失败!").arg(logMsg[componentSelection-1]),2,false);
    }
    emit syncParameters();
}

/**
 * @brief 增益1值改变槽函数实现
 */
void ControlModuleParametersWidget::onGain1ValueChanged()
{
    if (!m_device) return;
    
    // 直接调用设备的setMCPGain方法，同时更新gain1和gain2
    CommandResult result = m_device->setMCPGain(getGain1(), getGain2());
    if(CommandResult::Success==result)
    {
        emit writeLog(QString("增益1设置成功: %1V").arg(getGain1()),0,true);
    }
    else
    {
        emit writeLog(QString("增益1设置失败: %1V").arg(getGain1()),2,false);
    }
    emit syncParameters();
}

/**
 * @brief 增益2值改变槽函数实现
 */
void ControlModuleParametersWidget::onGain2ValueChanged()
{
    if (!m_device) return;
    
    // 直接调用设备的setMCPGain方法，同时更新gain1和gain2
    CommandResult result = m_device->setMCPGain(getGain1(), getGain2());
    if(CommandResult::Success==result)
    {
        emit writeLog(QString("增益2设置成功: %1V").arg(getGain2()),0,true);
    }
    else
    {
        emit writeLog(QString("增益2设置失败: %1V").arg(getGain2()),2,false);
    }
    emit syncParameters();
}

/**
 * @brief 阴极门控开关槽函数实现
 */
void ControlModuleParametersWidget::onCathodeGatingToggled(bool checked)
{
    if (!m_device) return;
    
    static QString logMsg[]={"阴极门控+外触发打开","阴极门控打开","阴极门控关闭"};

    CommandResult result = m_device->setCathodeGating(
        getCathodeGatingMode(),
        getDelayTime(),
        getPulseWidth()
    );
    if(CommandResult::Success==result)
    {
        emit writeLog(QString("%1成功!").arg(logMsg[getCathodeGatingMode()-1]),0,true);
    }
    else
    {
        emit writeLog(QString("%1失败!").arg(logMsg[getCathodeGatingMode()-1]),2,false);
    }
    ui->delayTimeSpinBox->setEnabled(checked&&!ui->widget_External->isChecked());
    ui->pulseWidthSpinBox->setEnabled(checked&&!ui->widget_External->isChecked());
    if(!checked && ui->widget_External->isChecked()){
        ui->widget_External->setChecked(checked);
    }
    ui->widget_External->setEnabled(checked);
    emit syncParameters();
}

/**
 * @brief 外部触发开关槽函数实现
 */
void ControlModuleParametersWidget::onExternalToggled(bool checked)
{
    if (!m_device) return;
    
    static QString logMsg[]={"阴极门控+外触发打开","阴极门控打开","阴极门控关闭"};
    Q_UNUSED(checked)
    int _m = getCathodeGatingMode();
    if(_m==3)
    {
        return;
    }
    ui->delayTimeSpinBox->setEnabled(_m == 2);
    ui->pulseWidthSpinBox->setEnabled(_m == 2);
    CommandResult result = m_device->setCathodeGating(
        _m,
        getDelayTime(),
        getPulseWidth()
    );
    if(CommandResult::Success==result)
    {
        emit writeLog(QString("%1成功!").arg(logMsg[_m-1]),0,true);
    }
    else
    {
        emit writeLog(QString("%1失败!").arg(logMsg[_m-1]),2,false);
    }
    emit syncParameters();
}

/**
 * @brief 延迟时间改变槽函数实现
 */
void ControlModuleParametersWidget::onDelayTimeValueChanged()
{
    if (!m_device) return;

    if (getCathodeGatingMode()!=3) {
        CommandResult result = m_device->setCathodeGating(
            getCathodeGatingMode(),
            getDelayTime(),
            getPulseWidth()
        );
        if(CommandResult::Success==result)
        {
            emit writeLog(QString("延迟时间设置成功: %1ns").arg(getDelayTime()),0,true);
        }
        else
        {
            emit writeLog(QString("延迟时间设置失败: %1ns").arg(getDelayTime()),2,false);
        }
        emit syncParameters();
    }
}

/**
 * @brief 脉冲宽度改变槽函数实现
 */
void ControlModuleParametersWidget::onPulseWidthValueChanged()
{
    if (!m_device) return;
    
    if (getCathodeGatingMode()!=3) {
        CommandResult result = m_device->setCathodeGating(
            getCathodeGatingMode(),
            getDelayTime(),
            getPulseWidth()
        );
        if(CommandResult::Success==result)
        {
            emit writeLog(QString("脉冲宽度设置成功: %1ns").arg(getPulseWidth()),0,true);
        }
        else
        {
            emit writeLog(QString("脉冲宽度设置失败: %1ns").arg(getPulseWidth()),2,false);
        }
        emit syncParameters();
    }
}
